package mornd.test3;

import org.omg.PortableInterceptor.ServerRequestInterceptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * @author: mornd
 * @dateTime: 2023/5/4 - 16:52
 */
public class TestApplicationContext {

    static class Config { }

    static class Bean1 {
        private Bean2 bean2;
        public Bean2 getBean2() {
            return bean2;
        }

        public void setBean2(Bean2 bean2) {
            this.bean2 = bean2;
        }
    }
    static class Bean2 { }

    public static void main(String[] args) {
//        getClassPathXml();
//        getClassPathXml2();
//        getFileSystem();
//        testAnnotationConfig();
        testAnnotationConfigServletWebServer();
    }

    private static void getClassPathXml() {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("b01.xml");
        System.out.println(context.getBean(Bean1.class));
    }

    /**
     * 自定义方式
     */
    private static void getClassPathXml2() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        System.out.println(beanFactory.getBeanDefinitionCount());
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(new ClassPathResource("b01.xml"));
        //reader.loadBeanDefinitions(new FileSystemResource("xxxxx/b01.xml"));
        System.out.println(beanFactory.getBeanDefinitionCount());
        System.out.println(beanFactory.getBean(Bean1.class));
    }

    private static void getFileSystem() {
        FileSystemXmlApplicationContext context =
                new FileSystemXmlApplicationContext("E:\\idea_work_space2023\\springSourceCode\\_01_container\\src\\main\\resources\\b01.xml");
        System.out.println(context.getBean(Bean1.class));
    }

    private static void testAnnotationConfig() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class);
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
            /*
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    testApplicationContext.Config
             */
        }
    }

    /**
     * spring boot
     */
    private static void testAnnotationConfigServletWebServer() {
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        String[] names = context.getBeanDefinitionNames();
        Arrays.stream(names).forEach(System.out::println);
    }

    @Configuration
    static class WebConfig {

        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            TomcatServletWebServerFactory tomcatServletWebServerFactory =
                    new TomcatServletWebServerFactory();
            //tomcatServletWebServerFactory.setPort(8081);
            tomcatServletWebServerFactory.setUriEncoding(StandardCharsets.UTF_8);
            return tomcatServletWebServerFactory;
        }

        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        // 注册dispatcherServlet 到 web 服务器中，这3个组件缺一不可
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        //@Bean
        public CharacterEncodingFilter characterEncodingFilter() {
            CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
            characterEncodingFilter.setEncoding("utf-8");
            characterEncodingFilter.setForceRequestEncoding(true);
            characterEncodingFilter.setForceResponseEncoding(true);
            return characterEncodingFilter;
        }

        // 这里规定 bean 的每次以/开头代表请求的路径，这里浏览器访问 /hello
        @Bean("/hello")
        public Controller controller() {
            return new Controller() {
                @Override
                public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                    String name = request.getParameter("name");
                    System.out.println(name);
                    response.getWriter().write("hello," + name);
                    return null;
                }
            };
        }
    }


}
